/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "gtest/gtest.h"
#include "test_helper.h"

#include "plugins/ecmascript/runtime/ecma_vm.h"
#include "include/runtime.h"
#include "include/runtime_options.h"
#include "runtime/regexp/ecmascript/regexp_parser.h"
#include "plugins/ecmascript/runtime/regexp/regexp_executor.h"
#include "plugins/ecmascript/runtime/object_factory.h"
#include "plugins/ecmascript/runtime/ecma_string-inl.h"

namespace ark::test {

// NOLINTNEXTLINE(google-build-using-namespace)
using namespace ark::ecmascript;
using MatchResult = RegExpMatchResult<JSHandle<EcmaString>>;
using RegExpExecutor = ark::ecmascript::RegExpExecutor;

// NOLINTBEGIN(readability-magic-numbers)

class RegExpTest : public testing::Test {
public:
    static void SetUpTestCase()
    {
        GTEST_LOG_(INFO) << "SetUpTestCase";
    }

    static void TearDownTestCase()
    {
        GTEST_LOG_(INFO) << "TearDownCase";
    }

    void SetUp() override
    {
        TestHelper::CreateEcmaVMWithScope(instance_, thread_, scope_);
    }

    void TearDown() override
    {
        TestHelper::DestroyEcmaVMWithScope(instance_, scope_);
    }

protected:
    // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
    JSThread *thread_ {nullptr};

private:
    PandaVM *instance_ {nullptr};
    EcmaHandleScope *scope_ {nullptr};
};

TEST_F(RegExpTest, ParseAndExec1)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("ab");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("abc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("ab");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec2)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(((ab)|(cd)|(de))|((ef)|(gh)|(jk)))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("cabd");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 10U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("ab");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str) == 0);
    ASSERT_TRUE(result.captures[3].second->Compare(*str) == 0);
    ASSERT_TRUE(result.captures[4].first);
    ASSERT_TRUE(result.captures[5].first);
    ASSERT_TRUE(result.captures[6].first);
    ASSERT_TRUE(result.captures[7].first);
    ASSERT_TRUE(result.captures[8].first);
    ASSERT_TRUE(result.captures[9].first);
}

TEST_F(RegExpTest, ParseAndExec3)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(aa|aabaac|ba|b|c)*");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("aabaac");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("aaba");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("ba");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec4)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a*");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("aabaac");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("aa");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec5)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a?");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("b");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec6)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(z)((a+)?(b+)?(c))*");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("zaacbbbcac");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 6U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("zaacbbbcac");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("z");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("ac");
    JSHandle<EcmaString> str4 = factory->NewFromCanBeCompressString("a");
    JSHandle<EcmaString> str5 = factory->NewFromCanBeCompressString("c");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str3) == 0);
    ASSERT_TRUE(result.captures[3].second->Compare(*str4) == 0);
    ASSERT_TRUE(result.captures[4].first);
    ASSERT_TRUE(result.captures[5].second->Compare(*str5) == 0);
}

TEST_F(RegExpTest, ParseAndExec7)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("^abc");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 4);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("ab\nabc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("abc");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec8)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("abc$");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 4);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("ab\nabc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("abc");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec9)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("er\\B");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("erv");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("er");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec10)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("d\\b");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("bad good");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("d");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec11)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source(".");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("\na");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("a");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec12)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source(".");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 8);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("\n");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("\n");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec13)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("abc");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 4);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("\naabc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("abc");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec14)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("abc");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 4);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("\nbbabc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("abc");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec15)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a(?=a)");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("aabc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("a");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec16)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("abc");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("ABC");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("ABC");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec17)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a\\n");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("a\n");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("a\n");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec18)
{
    RegExpParser parser = RegExpParser();
    PandaString source("a(?=a)");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("ababc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_FALSE(ret);
}

TEST_F(RegExpTest, ParseAndExec19)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a(?!a)");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("ababc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("a");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec20)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(?=(a+))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("baaabac");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("aaa");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec21)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a(?=a(?=b))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("caab");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("a");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec22)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source(".+:");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("aaaa:aa");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("aaaa:");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec23)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a(?<=a(?<!b))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("caab");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("a");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec24)
{
    RegExpParser parser = RegExpParser();
    PandaString source("a(?<=ab(?<!bc))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("caab");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_FALSE(ret);
}

TEST_F(RegExpTest, ParseAndExec25)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(?<=(ab))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("cabab");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("ab");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec26)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("[a-z]");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("A");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("A");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec27)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("[^a-b]");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("Z");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("Z");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec28)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("\\s");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("\n");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("\n");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec29)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("()|");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input;
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec30)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("|()");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input;
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
    ASSERT_TRUE(result.captures[1].first);
}

TEST_F(RegExpTest, ParseAndExec31)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a(a|b)\\1");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("aabb");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("abb");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("b");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec32)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(a(a|b))\\2");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("aabb");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 3U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("abb");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("ab");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("b");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str3) == 0);
}

TEST_F(RegExpTest, ParseAndExec33)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("qya+");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("qyqya");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("qya");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec34)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("qy(?=\\s+)");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("qyqy ");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("qy");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec35)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source(R"((\d{4})-(\d{2})-(\d{2}))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("xx2021-01-09");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 4U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("2021-01-09");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("2021");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("01");
    JSHandle<EcmaString> str4 = factory->NewFromCanBeCompressString("09");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str3) == 0);
    ASSERT_TRUE(result.captures[3].second->Compare(*str4) == 0);
}

TEST_F(RegExpTest, ParseAndExec36)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("quick\\s(brown).+?(jumps)");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("The Quick Brown Fox Jumps Over The Lazy Dog");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 3U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("Quick Brown Fox Jumps");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("Brown");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("Jumps");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str3) == 0);
}

TEST_F(RegExpTest, ParseAndExec37)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(ab){1,2}?c");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("abABc");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("abABc");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("AB");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec38)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("^(([a-z]+)*[a-z]\\.)+[a-z]{2,}$");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("www.netscape.com");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 3U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("www.netscape.com");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("netscape.");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("netscap");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str3) == 0);
}

TEST_F(RegExpTest, ParseAndExec39)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(a*)b\\1+");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("baaaac");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("b");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec40)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a*?");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("ab");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec41)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(.*?)a(?!(a+)b\\2c)\\2(.*)");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("baaabaac");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 4U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("baaabaac");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("ba");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("abaac");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].first);
    ASSERT_TRUE(result.captures[3].second->Compare(*str3) == 0);
}

TEST_F(RegExpTest, ParseAndExec42)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("[a-c\\d]+");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("\n\n\\abc324234");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("abc324234");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec43)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("[\\d][\n][^\\d]");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("line1\nline2");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("1\nl");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec44)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source(".[\b].");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("abc\bdef");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("c\bd");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec45)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("[^\b]+");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("easy\bto\u0008ride");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("easy");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec46)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("([\\S]+([ \t]+[\\S]+)*)[ \t]*=[ \t]*[\\S]+");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("Course_Creator = Test");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 3U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("Course_Creator = Test");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("Course_Creator");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_FALSE(result.captures[1].first);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].first);
}

TEST_F(RegExpTest, ParseAndExec47)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("[^o]t\\b");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("pilOt\nsoviet robot\topenoffice");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("et");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec49)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(a(b)\\4(5)(5))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 2);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("ab55");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 5U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("ab55");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("ab55");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("b");
    JSHandle<EcmaString> str4 = factory->NewFromCanBeCompressString("5");
    JSHandle<EcmaString> str5 = factory->NewFromCanBeCompressString("5");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures[2].second->Compare(*str3) == 0);
    ASSERT_TRUE(result.captures[3].second->Compare(*str4) == 0);
    ASSERT_TRUE(result.captures[4].second->Compare(*str5) == 0);
}
/*
TEST_F(RegExpTest, ParseAndExec50)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(?<year>\\d{4})-(?<date>\\d{2}-(?<day>\\d\\d))");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("2020-12-31");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread, ret);
    ASSERT_EQ(result.captures_.size(), 4U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("2020-12-31");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("2020");
    JSHandle<EcmaString> str3 = factory->NewFromCanBeCompressString("12-31");
    JSHandle<EcmaString> str4 = factory->NewFromCanBeCompressString("31");
    ASSERT_TRUE(result.captures_[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures_[1].second->Compare(*str2) == 0);
    ASSERT_TRUE(result.captures_[2].second->Compare(*str3) == 0);
    ASSERT_TRUE(result.captures_[3].second->Compare(*str4) == 0);
}
*/
TEST_F(RegExpTest, ParseAndExec51)
{
    RegExpParser parser = RegExpParser();
    PandaString source("\\u0000");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    // NOLINTNEXTLINE(bugprone-string-literal-with-embedded-nul)
    std::u16string input(u"\u0000");
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length() + 1,
                                parser.GetOriginBuffer(), true);
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
}

TEST_F(RegExpTest, ParseAndExec52)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("(aa).+\\1");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("aabcdaabcd");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 2U);
    JSHandle<EcmaString> str1 = factory->NewFromCanBeCompressString("aabcdaa");
    JSHandle<EcmaString> str2 = factory->NewFromCanBeCompressString("aa");
    ASSERT_TRUE(result.captures[0].second->Compare(*str1) == 0);
    ASSERT_TRUE(result.captures[1].second->Compare(*str2) == 0);
}

TEST_F(RegExpTest, ParseAndExec53)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("\\x01");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    std::u16string input(u"\u0001");
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(),
                                parser.GetOriginBuffer(), true);
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("\u0001");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec54)
{
    RegExpParser parser = RegExpParser();
    PandaString source("\\bot");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("pilot\nsoviet robot\topenoffice");
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(),
                                parser.GetOriginBuffer(), false);
    ASSERT_FALSE(ret);
}

TEST_F(RegExpTest, ParseAndExec55)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("e\\b");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    PandaString input("c\u0065");
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(),
                                parser.GetOriginBuffer(), false);
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("e");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec56)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("a啊");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    std::u16string input(u"a啊");
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.length(),
                                parser.GetOriginBuffer(), true);
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromString("a啊");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec57)
{
    RegExpParser parser = RegExpParser();
    PandaString source("\\udf06");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 16);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    // NOLINTNEXTLINE(modernize-avoid-c-arrays)
    char16_t data[] = {0xd834, 0xdf06};
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(data), 0, 2, parser.GetOriginBuffer(), true);
    ASSERT_FALSE(ret);
}

TEST_F(RegExpTest, ParseAndExec58)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("\\udf06");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);
    RegExpExecutor executor;
    // NOLINTNEXTLINE(modernize-avoid-c-arrays)
    char16_t data[] = {0xd834, 0xdf06};
    bool ret = executor.Execute(reinterpret_cast<const uint8_t *>(data), 0, 2, parser.GetOriginBuffer(), true);
    ASSERT_TRUE(ret);
    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    // NOLINTNEXTLINE(modernize-avoid-c-arrays)
    char16_t data1[] = {0xdf06};
    JSHandle<EcmaString> str = factory->NewFromUtf16(reinterpret_cast<const uint16_t *>(data1), 1);
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

TEST_F(RegExpTest, ParseAndExec59)
{
    ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
    RegExpParser parser = RegExpParser();
    PandaString source("\\v");
    parser.Init(const_cast<char *>(reinterpret_cast<const char *>(source.c_str())), source.size(), 0);
    parser.Parse();
    bool parseResult = parser.IsError();
    ASSERT_FALSE(parseResult);

    RegExpExecutor executor;
    PandaString input("\u000B");
    bool ret =
        executor.Execute(reinterpret_cast<const uint8_t *>(input.c_str()), 0, input.size(), parser.GetOriginBuffer());
    ASSERT_TRUE(ret);

    MatchResult result = executor.GetResult(thread_, ret);
    ASSERT_EQ(result.captures.size(), 1U);
    JSHandle<EcmaString> str = factory->NewFromCanBeCompressString("\u000B");
    ASSERT_TRUE(result.captures[0].second->Compare(*str) == 0);
}

}  // namespace ark::test

// NOLINTEND(readability-magic-numbers)
